#include "ice/ice_controller.h"
#include <rtc_base/logging.h>
#include <rtc_base/time_utils.h>
#include <absl/algorithm/container.h>
namespace xrtc
{
    const int a_is_better = 1;
    const int b_is_better = -1;
    const int k_min_improvement = 10;
    bool IceController::HasPingableConnection()
    {
        int64_t now = rtc::TimeMillis();
        for (auto conn : connections_)
        {
            if (IsPingable(conn, now))
            {
                return true;
            }
        }
        return false;
    }

    bool IceController::IsPingable(IceConnection *conn, int64_t now)
    {
        const Candidate &remote = conn->RemoteCandidate();
        if (remote.username.empty() || remote.password.empty())
        {
            RTC_LOG(LS_WARNING) << "remote ICE ufrag and pwd is empty,connot ping.";
            return false;
        }
        if (Weak())
        {
            return true;
        }
        return IsConnectionPastPingInterval(conn, now);
    }
    void IceController::AddConnection(IceConnection *conn)
    {

        connections_.push_back(conn);
        unpinged_connections_.insert(conn);
    }

    PingResult IceController::SelectConnectionToPing(int64_t last_ping_sent_ms)
    {

        bool need_ping_more_at_weak = false;
        for (auto conn : connections_)
        {
            if (conn->NumPingsSent() < MIN_PINGS_AT_WEAK_PING_INTERVAL)
            {
                need_ping_more_at_weak = true;
                break;
            }
        }

        int ping_interval = (Weak() || need_ping_more_at_weak) ? WEAK_PING_INTERVAL : STRONG_PING_INTERVAL;
        int64_t now = rtc::TimeMillis();
        const IceConnection *conn = nullptr;
        if (now >= last_ping_sent_ms + ping_interval)
        {
            conn = FindNextPingableConnection(now);
        }

        return PingResult(conn, ping_interval);
    }

    const IceConnection *IceController::FindNextPingableConnection(int64_t now)
    {

        if (selected_connection_ && selected_connection_->Writable() &&
            IsConnectionPastPingInterval(selected_connection_, now))
        {
            return selected_connection_;
        }
        bool has_pingable = false;
        for (auto conn : unpinged_connections_)
        {

            if (IsPingable(conn, now))
            {
                has_pingable = true;
                break;
            }
        }
        if (!has_pingable)
        {

            unpinged_connections_.insert(pinged_connections_.begin(), pinged_connections_.end());
            pinged_connections_.clear();
        }

        IceConnection *find_conn = nullptr;
        for (auto conn : unpinged_connections_)
        {
            if (!IsPingable(conn, now))
            {
                continue;
            }
            if (MorePingable(conn, find_conn))
            {
                find_conn = conn;
            }
        }

        return find_conn;
    }

    bool IceController::IsConnectionPastPingInterval(const IceConnection *conn, int64_t now)
    {

        int interval = GetConnectionPingInterval(conn, now);
        // RTC_LOG(LS_INFO) << "conn ping _interval:" << interval << ", LastPingSent: " << conn->LastPingSent();
        return now >= conn->LastPingSent() + interval;
    }

    int IceController::GetConnectionPingInterval(const IceConnection *conn, int64_t now)
    {

        if (conn->NumPingsSent() < MIN_PINGS_AT_WEAK_PING_INTERVAL)
        {

            return WEAK_PING_INTERVAL; // 48ms
        }
        if (Weak() || !conn->Stable(now))
        {

            return STABLING_CONNECTION_PING_INTERVAL; // 900ms
        }
        return STABLE_CONNECTION_PING_INTERVAL; // 2500ms
    }
    // 寻找更符合ping 条件的connection
    bool IceController::MorePingable(IceConnection *conn1, IceConnection *conn2)
    {

        if (!conn2)
        {
            return true;
        }
        if (!conn1)
        {
            return false;
        }

        if (conn1->LastPingSent() < conn2->LastPingSent())
        {
            return true;
        }
        if (conn1->LastPingSent() > conn2->LastPingSent())
        {
            return false;
        }

        return false;
    }
    int IceController::CompareConnections(IceConnection *a, IceConnection *b)
    {
        if (a->Writable() && !b->Writable())
        {
            return a_is_better;
        }
        if (!a->Writable() && b->Writable())
        {
            return b_is_better;
        }

        if (a->WriteState() < b->WriteState())
        {
            return a_is_better;
        }
        if (a->WriteState() > b->WriteState())
        {
            return b_is_better;
        }

        if (a->Receiving() && !b->Receiving())
        {
            return a_is_better;
        }
        if (!a->Receiving() && b->Receiving())
        {
            return b_is_better;
        }

        // 以上策略还是比较不了链路的优略的话，就比较优先级
        if (a->Priority() > b->Priority())
        {
            return a_is_better;
        }
        if (a->Priority() < b->Priority())
        {
            return b_is_better;
        }

        return 0;
    }
    bool IceController::ReadyToSend(IceConnection *conn)
    {
        return conn && (conn->Writable() || conn->WriteState() == IceConnection::STATE_WRITE_UNRELIABLE);
    }
    IceConnection *IceController::SortAndSwitchConnection()
    {
        absl::c_stable_sort(connections_, [this](IceConnection *conn1, IceConnection *conn2)
                            {
                                int cmp= CompareConnections(conn1,conn2);
                                if(cmp !=0 )
                                {
                                    return cmp>0;
                                } 
                            
                                return conn1->Rtt() <conn2->Rtt(); });

        RTC_LOG(LS_INFO) << "Sort " << connections_.size() << " available connections";
        for (auto conn : connections_)
        {

            RTC_LOG(LS_INFO) << conn->ToString();
        }
        IceConnection *top_connection = connections_.empty() ? nullptr : connections_[0];
        //  如果未准备发送数据（不具备发送数据的条件）或者 切换之前已经是选中的状态，不进行切换
        if (!ReadyToSend(top_connection) || selected_connection_ == top_connection)
        {
            return nullptr;
        }
        if (!selected_connection_)
        {
            return top_connection;
        }
        // 优势明显选择切换

        if (top_connection->Rtt() <= selected_connection_->Rtt() - k_min_improvement)
        {
            return top_connection;
        }
        return nullptr;
    }

    void IceController::MarkConnectionPinged(IceConnection *conn)
    {
        if (conn && pinged_connections_.insert(conn).second)
        {
            unpinged_connections_.erase(conn);
        }
    }
    void IceController::OnConnectionDestroyed(IceConnection *conn)
    {
        pinged_connections_.erase(conn);
        unpinged_connections_.erase(conn);
        auto iter = connections_.begin();
        for (; iter != connections_.end(); ++iter)
        {
            if (*iter == conn)
            {
                connections_.erase(iter);
                break;
            }
        }
    }

}